﻿using System;
using System.Collections.Generic;
using System.Text;
using DatabaseGroup.SSIS.SourceAdapters.View;
using DatabaseGroup.SSIS.SourceAdapters.Model;
using System.Globalization;

namespace DatabaseGroup.SSIS.SourceAdapters.Presenter
{
    /// <summary>
    /// Presenter for handling the General tab view
    /// </summary>
    public class GeneralTabPresenter
    {
        private readonly IEditorGeneralView _view;
        private readonly IComponentModel _componentModel;
        private GeneralTabSettings _settings;

        /// <summary>
        /// Initializes a new instance of the GeneralTabPresenter class
        /// using the view and model
        /// </summary>
        /// <param name="view">An instance of an IEditorGeneralView</param>
        /// <param name="componentModel">An instance of an IComponentModel</param>
        public GeneralTabPresenter(IEditorGeneralView view, IComponentModel componentModel)
        {
            _view = view;
            _componentModel = componentModel;

            PopulateViewLists();
            InitializeView();

            view.ViewSettings += view_ViewSettings;
            view.SavingSettings += view_SavingSettings;
            view.FileConnectionChange += view_FileConnectionChange;
        }

        /// <summary>
        /// Saves the current settings to the component metadata
        /// </summary>
        /// <param name="sender">The View</param>
        /// <param name="e"></param>
        private void view_SavingSettings(object sender, EventArgs e)
        {
            _componentModel.SetFileConnectionByName(_settings.FileConnection);
            _componentModel.ComponentName = _settings.ComponentName;
            _componentModel.ComponentDescription = _settings.ComponentDescription;

            _componentModel.SetProperty(PropertiesManager.CodePagePropName, PresenterUtils.ConvertStringToCodepage(_settings.CodePage));
            _componentModel.Locale = PresenterUtils.ConvertStringToLocaleID(_settings.Locale);
            _componentModel.SetProperty(PropertiesManager.IsUnicodePropName, _settings.IsUnicode);
            _componentModel.SetProperty(PropertiesManager.TextQualifierPropName,
                DelimiterStringConverter.ToValueDelim(_settings.TextQualifier));
            _componentModel.SetProperty(PropertiesManager.HeaderRowDelimiterPropName,
                DelimiterStringConverter.ToValueDelim(_settings.HeaderRowDelimiter));
            _componentModel.SetProperty(PropertiesManager.HeaderRowsToSkipPropName, _settings.HeaderRowsToSkip);
            _componentModel.SetProperty(PropertiesManager.DataRowsToSkipPropName, _settings.DataRowsToSkip);
        
            string escape = DelimiterStringConverter.ToValueDelim(_settings.EscapeChar);
            _componentModel.SetProperty(PropertiesManager.EscapeCharPropName, string.IsNullOrEmpty(escape) ? '\0' : escape[0]);
        
            _componentModel.SetProperty(PropertiesManager.ColumnNamesInFirstRowPropName, _settings.ColumnNamesInFirstDataRow);
            _componentModel.SetProperty(PropertiesManager.TrimWhitespacePropName, _settings.TrimWhiteSpace);
            _componentModel.SetProperty(PropertiesManager.TreatEmptyStringsAsNullPropName, _settings.TreatEmptyStringsAsNull);
        }

        /// <summary>
        /// Binds the view with the current settings object and validates
        /// the selected file connection manager
        /// </summary>
        /// <param name="sender">The View</param>
        /// <param name="e"></param>
        private void view_ViewSettings(object sender, TabEventArgs e)
        {
            if (e.Tab != EditorViewTab.General && e.Tab != EditorViewTab.ANY)
                return;

            _view.BindGeneralTab(_settings);
            ValidateFileConnectionManager();
        }

        /// <summary>
        /// Prompts the user for a new connection manager if requested,
        /// validates the newly selected manager
        /// </summary>
        /// <param name="sender">The View</param>
        /// <param name="e"></param>
        private void view_FileConnectionChange(object sender, EventArgs e)
        {
            if (_settings.FileConnection == MessageStrings.NewFileConnection)
            {
                string newFileConnection = _componentModel.RequestNewFileConnection();

                if (!string.IsNullOrEmpty(newFileConnection))
                    _settings.FileConnection = newFileConnection;
                else
                    _settings.FileConnection = string.Empty;

                RefreshViewFileConnections();
            }

            ValidateFileConnectionManager();
        }

        /// <summary>
        /// Creates a new general settings object and loads it with the current
        /// component configuration and binds it to the view
        /// </summary>
        private void InitializeView()
        {
            _settings = new GeneralTabSettings();

            _settings.FileConnection = _componentModel.FileConnectionName;

            if (string.IsNullOrEmpty(_settings.FileConnection))
                _settings.FileConnection = string.Empty;

            _settings.ComponentName = _componentModel.ComponentName;
            _settings.ComponentDescription = _componentModel.ComponentDescription;

            _settings.Locale = PresenterUtils.ConvertLocaleIDToString(_componentModel.Locale);
            _settings.CodePage = PresenterUtils.ConvertCodepageToString(_componentModel.GetProperty<int>(PropertiesManager.CodePagePropName));
            _settings.IsUnicode = _componentModel.GetProperty<bool>(PropertiesManager.IsUnicodePropName);
            _settings.TextQualifier =
                DelimiterStringConverter.ToReadableDelim(_componentModel.GetProperty<string>(PropertiesManager.TextQualifierPropName));
            _settings.HeaderRowDelimiter =
                DelimiterStringConverter.ToReadableDelim(_componentModel.GetProperty<string>(PropertiesManager.HeaderRowDelimiterPropName));
            _settings.HeaderRowsToSkip = _componentModel.GetProperty<int>(PropertiesManager.HeaderRowsToSkipPropName);
            _settings.DataRowsToSkip = _componentModel.GetProperty<int>(PropertiesManager.DataRowsToSkipPropName);
            _settings.EscapeChar =
                DelimiterStringConverter.ToReadableDelim(((char)_componentModel.GetProperty<ushort>(PropertiesManager.EscapeCharPropName)).ToString());
            _settings.ColumnNamesInFirstDataRow = _componentModel.GetProperty<bool>(PropertiesManager.ColumnNamesInFirstRowPropName);
            _settings.TrimWhiteSpace = _componentModel.GetProperty<bool>(PropertiesManager.TrimWhitespacePropName);
            _settings.TreatEmptyStringsAsNull = _componentModel.GetProperty<bool>(PropertiesManager.TreatEmptyStringsAsNullPropName);

            _view.BindGeneralTab(_settings);
            RefreshViewFileConnections();
        }

        /// <summary>
        /// Sets up the drop downs on the general tab view with their list items
        /// </summary>
        private void PopulateViewLists()
        {
            List<string> codePages = new List<string>();

            foreach (EncodingInfo encodingInfo in Encoding.GetEncodings())
            {
                string codepage = string.Format("{0} ({1})", encodingInfo.CodePage, encodingInfo.DisplayName);
                codePages.Add(codepage);
            }

            _view.PopulateCodePageList(codePages.ToArray());

            CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
            string[] locales = new string[cultures.Length];
            int localeIndex = 0;

            foreach (CultureInfo ci in cultures)
            {
                locales[localeIndex++] = string.Format("{0} <{1}>", ci.EnglishName, ci.LCID);
            }

            Array.Sort(locales);

            _view.PopulateLocaleList(locales);
        }

        /// <summary>
        /// Populates the views list of file connections with
        /// all file connections currently avaliable
        /// </summary>
        private void RefreshViewFileConnections()
        {
            List<string> fileConnections = _componentModel.GetAvailableFileConnectionNames();
            fileConnections.Insert(0, string.Empty);
            _view.PopulateFileConnections(fileConnections, _settings.FileConnection);
        }

        /// <summary>
        /// Validates the file connection manager and displays an error if invalid
        /// </summary>
        private void ValidateFileConnectionManager()
        {
            // TODO: MessageStrings
            if (!_componentModel.IsFileConnectionValid(_settings.FileConnection))
                _view.ShowErrorMessage("No cool file dude.");
            else
                _view.HideErrorMessage();
        }
    }
}
